/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;

namespace DaveSexton.DocProject.DocSites
{
	internal sealed class BinaryQueryOperation : MultiQueryOperation
	{
		#region Public Properties
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public QueryExpression First
		{
			get
			{
				return OperandsList[0];
			}
		}

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public QueryExpression Second
		{
			get
			{
				IList<QueryExpression> operands = OperandsList;

				return (operands.Count > 1) ? operands[1] : null;
			}
			set
			{
				if (IsOptimized && value != null && !value.IsOptimized)
					OperandsList[1] = value.Optimize();
				else if (value == null)
				{
					if (OperandCount > 1)
						OperandsList.RemoveAt(1);
				}
				else
					OperandsList[1] = value;

				if (OperandsList.Count > 1)
					OperandsList[1].Parent = this;
			}
		}
		#endregion

		#region Private / Protected
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="BinaryQueryOperation" /> class.
		/// </summary>
		public BinaryQueryOperation(QueryExpression first, QueryOperator op)
			: base(op, first)
		{
			if (first == null)
				throw new ArgumentNullException("first");
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BinaryQueryOperation" /> class.
		/// </summary>
		public BinaryQueryOperation(QueryExpression first, QueryOperator op, QueryExpression second)
			: base(op, first, second)
		{
			if (first == null)
				throw new ArgumentNullException("first");
		}

		/// <summary>
		/// Constructs a new instance of the <see cref="BinaryQueryOperation" /> class.
		/// </summary>
		private BinaryQueryOperation(QueryExpression first, QueryOperator op, QueryExpression second, bool optimized)
			: base(op, optimized, first, second)
		{
		}
		#endregion

		#region Methods
		public override QueryExpression Normalize()
		{
			IList<QueryExpression> operands = OperandsList;

			if (operands.Count == 0)
				return EmptyQueryExpression.Value;

			QueryExpression first = (operands[0] ?? EmptyQueryExpression.Value).Normalize();
			QueryExpression second = (((operands.Count > 1) ? operands[1] : null) ?? EmptyQueryExpression.Value).Normalize();

			if (first is EmptyQueryExpression)
				return second;
			else if (second is EmptyQueryExpression)
				return first;
			else
				return new BinaryQueryOperation(first, Operator, second, IsOptimized);
		}
		#endregion
	}
}
